package com.jieli.stream.dv.running2.camera;

import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;

import com.jieli.lib.dv.control.projection.StreamingPush;
import com.jieli.lib.dv.control.projection.beans.StreamType;
import com.jieli.stream.dv.running2.util.ClientManager;
import com.jieli.stream.dv.running2.util.Dbug;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import static com.jieli.stream.dv.running2.util.IConstant.PROJECTION_HEIGHT;
import static com.jieli.stream.dv.running2.util.IConstant.PROJECTION_WIDTH;

public class CameraPresenter implements ICamera, Camera.PreviewCallback {
    private static final String tag = CameraPresenter.class.getSimpleName();
    private int mCurrentCamIndex = 0;
    private boolean previewing;
    private Camera mCamera;
    private StreamingPush mStreaming;
    private boolean isReady;
    private byte[] mPreviewBuffer;
    private SurfaceTexture mSurfaceTexture;

    public CameraPresenter() {
        mStreaming = new StreamingPush(StreamingPush.Protocol.TCP);
    }

    /**
     * 设置设备是否准备好的状态
     * @param isReady 设备是否已准备好
     */
    public void setDeviceState(boolean isReady) {
        this.isReady = isReady;
    }

    /**
     * 预览状态
     * @return 是否处于预览中
     */
    @Override
    public boolean isPreviewing() {
        return this.previewing;
    }

    /**
     * 使用SurfaceView的holder surface来预览
     * @param holder 用于预览的载体
     */
    @Override
    public void startPreview(SurfaceHolder holder) {
        if (mCamera != null) {
            try {
                mCamera.setPreviewDisplay(holder);
            } catch (IOException e) {
                e.printStackTrace();
            }
            mCamera.startPreview();
            previewing = true;
        }
    }

    /**
     * 使用Texture来预览，这里只用其自带buffer来缓冲数据
     * @param texture 用于预览的载体
     */
    @Override
    public void startPreview(SurfaceTexture texture) {
        Dbug.i(tag, "startPreview ");
        mSurfaceTexture = texture;
        if (mCamera != null) {
            try {
                mCamera.setPreviewTexture(texture);
            } catch (IOException e) {
                mCamera.release();
                mCamera = null;
                e.printStackTrace();
            }
            int width = mCamera.getParameters().getPreviewSize().width;
            int height = mCamera.getParameters().getPreviewSize().height;
            Dbug.i(tag, "startPreview: w=" + width+", h="+ height);
            int bufferSize = width * height * ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
            mPreviewBuffer = new byte[bufferSize];
            mCamera.addCallbackBuffer(mPreviewBuffer);
            mCamera.setPreviewCallbackWithBuffer(this);

            mCamera.startPreview();
            previewing = true;
        }
    }

    /**
     * 停止预览
     */
    @Override
    public void stopPreview() {
        if (mCamera != null) {
            mCamera.stopPreview();
        }
    }

    /**
     * 打开手机摄像头，创建数据的发送通道
     * @return 是否成功
     */
    @Override
    public boolean open() {
        Dbug.i(tag, "open ");
        int cameraCount;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras();

        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
            Camera.getCameraInfo(camIdx, cameraInfo);
            //在这里打开的是前/后置摄像头
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                try {
                    mCamera = Camera.open(camIdx);
                    mCurrentCamIndex = camIdx;
                } catch (RuntimeException e) {
                    Log.e(tag, "Camera failed to open: " + e.getLocalizedMessage());
                    return false;
                }
            }
        }
        mStreaming.create(ClientManager.getClient().getAddress());
        mCamera.setPreviewCallback(this);
        return true;
    }

    /**
     * 关闭发送通道和关闭相机
    * */
    @Override
    public void close() {
        if (mStreaming != null)
            mStreaming.close();
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
        previewing = false;
    }

    /**
     * 旋转屏幕后自动适配（若只用到竖的，也可不要）
     */
    @Override
    public void setDisplayOrientation(int rotation) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(mCurrentCamIndex, info);

        int result;
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0: degrees = 0; break;
            case Surface.ROTATION_90: degrees = 90; break;
            case Surface.ROTATION_180: degrees = 180; break;
            case Surface.ROTATION_270: degrees = 270; break;
        }

        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {
            // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        mCamera.setDisplayOrientation(result);
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        if (mCamera == null || camera == null) {
             Dbug.e(tag, "onPreviewFrame: camera null");
            return;
        }
        if (mSurfaceTexture != null) {
            camera.addCallbackBuffer(mPreviewBuffer);
            //mCamera.setPreviewTexture(holder);
            mSurfaceTexture.getTimestamp();
        }
        Camera.Parameters parameters = camera.getParameters();
        if (parameters == null) {
            Dbug.e(tag, "onPreviewFrame: parameters null");
            return;
        }
        Camera.Size previewSize = parameters.getPreviewSize();
        YuvImage image = new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null); //ImageFormat.NV21  640 480
        ByteArrayOutputStream outputSteam = new ByteArrayOutputStream();
        // 将NV21格式图片，以质量60压缩成Jpeg，并得到JPEG数据流
        boolean isCompressSuccess = image.compressToJpeg(new Rect(0, 0, PROJECTION_WIDTH, PROJECTION_HEIGHT), 60, outputSteam);
        //Dbug.i(tag, "w="+ image.getWidth()+", h="+ image.getHeight()+", isCompressSuccess="+ isCompressSuccess+", isReady="+isReady);
        if (isCompressSuccess) {
            byte[] jpegData = outputSteam.toByteArray();
            if (mStreaming != null && isReady) {
                mStreaming.send(StreamType.TYPE_JPEG, jpegData);
            }
        } else {
            Dbug.e(tag, "compressToJpeg failed");
        }
    }
}
